package com.ruoyi.system.util;

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import javax.imageio.ImageIO;
import javax.imageio.ImageReader;
import javax.imageio.stream.ImageInputStream;
import java.awt.image.BufferedImage;
import java.io.File;
import java.io.InputStream;
import java.util.Iterator;

/**
 * TIFF帧提取工具：支持从输入流读取TIFF，截取指定帧保存为PNG/JPG
 */
public class TiffFrameTool {
    private static final Logger log = LoggerFactory.getLogger(TiffFrameTool.class);
    private static final String[] SUPPORTED_FORMATS = {"png", "jpg"}; // 支持的目标格式
    private static final int DEFAULT_FRAME_INDEX = 0; // 默认截取第一帧

    /**
     * 重载方法：默认截取第一帧，保存为PNG
     * @param tiffIn TIFF输入流（如上传流、本地文件流）
     * @param savePath 保存路径（如 D:/frames/test.png）
     * @return 保存结果（true成功，false失败）
     */
    public static boolean extractFrame(InputStream tiffIn, String savePath) {
        return extractFrame(tiffIn, savePath, DEFAULT_FRAME_INDEX, "png");
    }

    /**
     * 核心方法：自定义帧索引和保存格式
     * @param tiffIn TIFF输入流
     * @param savePath 保存路径
     * @param frameIndex 帧索引（0=第一帧）
     * @param targetFormat 目标格式（png/jpg）
     * @return 保存结果
     */
    public static boolean extractFrame(InputStream tiffIn, String savePath, int frameIndex, String targetFormat) {
        // 1. 参数校验
        if (tiffIn == null) {
            log.error("TIFF输入流为空");
            return false;
        }
        if (!isSupportedFormat(targetFormat)) {
            log.error("不支持的目标格式：{}，仅支持{}", targetFormat, String.join("/", SUPPORTED_FORMATS));
            return false;
        }

        // 2. 初始化TIFF读取器（try-with-resources自动释放资源）
        try (ImageInputStream imageIn = ImageIO.createImageInputStream(tiffIn)) {
            // 获取TIFF专用读取器
            Iterator<ImageReader> readers = ImageIO.getImageReadersByFormatName("TIFF");
            if (!readers.hasNext()) {
                log.error("未找到TIFF解码器，请检查TwelveMonkeys依赖是否正确引入");
                return false;
            }
            ImageReader tiffReader = readers.next();
            tiffReader.setInput(imageIn, false); // 不自动关闭流（外部管理）

            // 3. 校验帧索引有效性
            int totalFrames = tiffReader.getNumImages(true); // 获取总帧数
            if (frameIndex < 0 || frameIndex >= totalFrames) {
                log.error("帧索引{}无效，TIFF共{}帧", frameIndex, totalFrames);
                return false;
            }

            // 4. 读取指定帧
            BufferedImage frame = tiffReader.read(frameIndex);
            if (frame == null) {
                log.error("读取第{}帧失败", frameIndex);
                return false;
            }

            // 5. 处理JPG透明通道问题（JPG不支持透明，转为RGB）
            if ("jpg".equalsIgnoreCase(targetFormat) && frame.getAlphaRaster() != null) {
                BufferedImage rgbFrame = new BufferedImage(
                        frame.getWidth(), frame.getHeight(),
                        BufferedImage.TYPE_INT_RGB
                );
                rgbFrame.createGraphics().drawImage(frame, 0, 0, null);
                frame = rgbFrame;
                log.info("JPG格式自动处理透明通道，转为RGB");
            }

            // 6. 保存文件（确保父目录存在）
            File saveFile = new File(savePath);
            File parentDir = saveFile.getParentFile();
            if (parentDir != null && !parentDir.exists() && !parentDir.mkdirs()) {
                log.error("创建父目录失败：{}", parentDir.getAbsolutePath());
                return false;
            }

            boolean success = ImageIO.write(frame, targetFormat, saveFile);
            if (success) {
                log.info("TIFF帧保存成功：{}（帧索引{}，格式{}）", savePath, frameIndex, targetFormat);
            } else {
                log.error("TIFF帧保存失败：{}", savePath);
            }
            return success;

        } catch (Exception e) {
            log.error("TIFF帧处理异常", e);
            return false;
        }
    }

    /**
     * 校验目标格式是否支持
     */
    private static boolean isSupportedFormat(String format) {
        for (String supported : SUPPORTED_FORMATS) {
            if (supported.equalsIgnoreCase(format)) {
                return true;
            }
        }
        return false;
    }
}